package com.yc.web.controller.common;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.yc.common.annotation.Log;
import com.yc.common.annotation.RateLimiter;
import com.yc.common.constant.HttpStatus;
import com.yc.common.core.domain.model.EditPassBody;
import com.yc.common.core.domain.model.LoginUser;
import com.yc.common.core.domain.model.RegisterBody;
import com.yc.common.enums.OperationType;
import com.yc.common.core.domain.AjaxResult;
import com.yc.common.core.domain.model.LoginBody;
import com.yc.common.exceptions.user.LogoutException;
import com.yc.common.utils.JwtUtil;
import com.yc.common.utils.StringUtil;
import com.yc.common.utils.WebUtil;
import com.yc.common.utils.ip.IpUtil;
import com.yc.framework.web.domain.TokenInfo;
import com.yc.framework.web.service.SysLoginService;
import com.yc.framework.web.service.SysRegisterService;
import com.yc.framework.web.service.TokenService;
import com.yc.system.service.ISysUserService;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

@Api(tags = "用户认证管理")
@RestController
public class SysAuthController {

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private SysRegisterService registerService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ISysUserService userService;

    /**
     * 登录方法
     *
     * @param loginUserDto 登录信息
     * @return 登录结果
     */
    @Log(module = "用户认证模块", type = OperationType.LOGIN, description = "用户登录")
    @ApiOperation("用户登录")
    @RateLimiter(permitsPerSecond = 3.0)
    @PostMapping("/login")
    public AjaxResult login(@Valid @RequestBody LoginBody loginUserDto) {

        AjaxResult ajax = AjaxResult.success("登录成功");

        //获取ip信息
        String ip = IpUtil.getLocalIpv4Address();

        TokenInfo tokenInfo = loginService.login(loginUserDto);

        ajax.put("tokenInfo", tokenInfo);
        ajax.put("ip", ip);

        return ajax;
    }

    /**
     * 用户注册
     *
     * @param registerUserDto 注册信息
     * @return 注册结果
     */
    @Log(module = "用户认证模块", type = OperationType.INSERT, description = "用户注册")
    @ApiOperation("用户注册")
    @RateLimiter(permitsPerSecond = 3.0)
    @PostMapping("/register")
    public AjaxResult register(@Valid @RequestBody RegisterBody registerUserDto) {

        AjaxResult ajax = AjaxResult.success();
        ajax.put("msg", "注册成功");

        registerService.register(registerUserDto);

        return ajax;
    }

    /**
     * 登出方法 - 结合API和Spring Security
     * 此方法会触发Spring Security的登出处理，由LogoutSuccessHandler负责响应
     */
    @ApiOperation("用户登出")
    @PostMapping("/logout")
    public void logout(HttpServletRequest request, HttpServletResponse response) {
        // 直接调用Spring Security的登出处理
        try {
            new SecurityContextLogoutHandler().logout(request, response,
                    SecurityContextHolder.getContext().getAuthentication());
        } catch (Exception e) {
            throw new LogoutException("登出处理异常: " + e.getMessage());
        }
    }

    /**
     * 获取当前用户菜单列表
     */
    @Log(module = "用户认证模块", type = OperationType.QUERY, description = "获取登录用户信息")
    @ApiOperation("获取登录用户信息")
    @RateLimiter(permitsPerSecond = 3.0)
    @GetMapping("/getLoginUserInfo")
    public AjaxResult getLoginUserInfo() {
        AjaxResult ajax = AjaxResult.success();

        // 获取用户令牌
        String token = WebUtil.getToken();
        String tokenId = null;

        try {
            // 验证令牌是否存在
            if (token == null || StringUtil.isEmpty(token)) {
                return AjaxResult.error();
            }
            //获取用户信息
            Claims claims = JwtUtil.parseJWT(token);
            JSONObject jsonObject = JSON.parseObject(claims.getSubject());
            tokenId = jsonObject.getString("jti");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        LoginUser loginUser = tokenService.getLoginUser(tokenId);
        if (loginUser == null) {
            return AjaxResult.error("用户已失效，请重新登录", HttpStatus.BAD_REQUEST);
        }

        // 返回登录用户信息
        ajax.put("userInfo", loginUser);
        return ajax;
    }

    @Log(module = "用户认证模块", type = OperationType.UPDATE, description = "修改密码")
    @ApiOperation("修改用户密码")
    @PostMapping("/editYourPass")
    public AjaxResult updateUserPass(@Valid @RequestBody EditPassBody editPassBody) {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("msg", "更新成功");

        userService.updateUserPassword(editPassBody);

        return ajax;
    }

}